<?php

namespace App\Controllers;

use App\Helpers\CommonUtil;
use CodeIgniter\HTTP\Files\UploadedFile;
use Exception;
use ZipArchive;

class Auth extends BaseController
{
    public function register(): \CodeIgniter\HTTP\ResponseInterface
    {
        $rules = [
            "username" => 'required|regex_match[/^[a-zA-Z\x80-\xff][a-zA-Z0-9\x80-\xff]{1,19}$/]|is_unique[user.username]',
            "mobile"   => 'required|regex_match[/^1[3-9]\d{9}$/]|is_unique[user.mobile]',
            "password" => 'required|min_length[6]|max_length[20]',
        ];

        $errorsMsg = [
            'username' => [
                'required'    => '用户名不能为空',
                'regex_match' => '用户名开头不能是数字, 长度为2-20个字符',
                'is_unique'   => '当前用户名已被使用',
            ],
            'mobile'   => [
                'required'    => '手机号码不能为空',
                'regex_match' => '手机号码规则不匹配',
                'is_unique'   => '当前手机号码已被使用',
            ],
            'password' => [
                'required'   => '密码不能为空',
                'min_length' => '密码长度至少包含6个字符',
                'max_length' => '密码长度不得大于20个字符',
            ],
        ];

        if (!$this->validate($rules, $errorsMsg)) {
            $errors = $this->validator->getErrors();

            return $this->responseMsg(array_shift($errors));
        }

        $post = $this->validator->getValidated();

        $username  = trim($post['username']);
        $mobile    = trim($post['mobile']);
        $password  = trim($post['password']);
        $loginTime = date('Y-m-d H:i:s');

        $data = [
            "username"    => $username,
            "mobile"      => $mobile,
            "password"    => md5($password),
            "token"       => md5($username . $password . $loginTime),
            "login_time"  => $loginTime,
            "create_time" => $loginTime
        ];

        $db = db_connect();
        $db->table('user')->insert($data);

        return $this->responseJson(["id" => $db->insertID(), "username" => $username, "token" => $data["token"]]);
    }

    public function login(): \CodeIgniter\HTTP\ResponseInterface
    {
        $rules = [
            "username" => 'required|min_length[2]|max_length[20]',
            "password" => 'required|min_length[6]|max_length[20]',
        ];

        $errorsMsg = [
            'username' => [
                'required'   => '账号不能为空',
                'min_length' => '账号长度至少包含2个字符',
                'max_length' => '账号长度不得大于20个字符',
            ],
            'password' => [
                'required'   => '密码不能为空',
                'min_length' => '密码长度至少包含6个字符',
                'max_length' => '密码长度不得大于20个字符',
            ],
        ];

        if (!$this->validate($rules, $errorsMsg)) {
            $errors = $this->validator->getErrors();

            return $this->responseMsg(array_shift($errors));
        }

        $post = $this->validator->getValidated();

        $username  = trim($post['username']);
        $password  = trim($post['password']);
        $loginTime = date('Y-m-d H:i:s');

        $db   = db_connect();
        $user = $db->table('user')->where('username', $username)->orWhere('mobile', $username)->get()->getRow();

        if (empty($user)) {
            return $this->responseMsg("当前用户不存在");
        }

        if ($user->password != md5($password)) {
            return $this->responseMsg("密码验证失败");
        }

        $token = md5($user->username . $user->password . $loginTime);

        $db->table('user')->where('id', $user->id)->update([
            "token"      => $token,
            "login_time" => $loginTime,
        ]);

        return $this->responseJson(["id" => $user->id, "username" => $user->username, "token" => $token]);
    }

    public function logout(): \CodeIgniter\HTTP\ResponseInterface
    {
        try {
            $user = $this->getUser();
        } catch (Exception $e) {
            return $this->responseMsg($e->getMessage());
        }

        db_connect()->table('user')->where('id', $user->id)->update(["token" => NULL, "login_time" => NULL]);

        return $this->responseMsg();
    }

    public function forget(): \CodeIgniter\HTTP\ResponseInterface
    {
        $rules = [
            "username" => 'required|regex_match[/^[a-zA-Z\x80-\xff][a-zA-Z0-9\x80-\xff]{1,19}$/]|is_not_unique[user.username]',
            "mobile"   => 'required|regex_match[/^1[3-9]\d{9}$/]|is_not_unique[user.mobile]',
            "password" => 'required|min_length[6]|max_length[20]',
        ];

        $errorsMsg = [
            'username' => [
                'required'      => '用户名不能为空',
                'regex_match'   => '用户名开头不能是数字, 长度为2-20个字符',
                'is_not_unique' => '当前用户名不存在',
            ],
            'mobile'   => [
                'required'      => '手机号码不能为空',
                'regex_match'   => '手机号码规则不匹配',
                'is_not_unique' => '当前手机号码不存在',
            ],
            'password' => [
                'required'   => '密码不能为空',
                'min_length' => '密码长度至少包含6个字符',
                'max_length' => '密码长度不得大于20个字符',
            ],
        ];

        if (!$this->validate($rules, $errorsMsg)) {
            $errors = $this->validator->getErrors();

            return $this->responseMsg(array_shift($errors));
        }

        $post     = $this->validator->getValidated();
        $username = $post['username'];
        $mobile   = $post['mobile'];

        $user = db_connect()->table('user')->where('username', $username)->where('mobile', $mobile)->get()->getRowObject();

        if (empty($user)) {
            return $this->responseMsg("用户名和手机号码不匹配");
        }

        db_connect()->table('user')->where('id', $user->id)->update(['password' => md5($post['password']), 'token' => '']);

        return $this->responseMsg();
    }

    public function check(): \CodeIgniter\HTTP\ResponseInterface
    {
        try {
            $this->getUser();
        } catch (Exception $e) {
            return $this->responseMsg($e->getMessage());
        }

        return $this->responseMsg();
    }

    public function profile(): \CodeIgniter\HTTP\ResponseInterface
    {
        try {
            $user = $this->getUser();

            $rules     = [
                "name"    => 'required|regex_match[/^.{2,10}$/]',
                "website" => 'if_exist|valid_url_strict',
                "avatar"  => 'if_exist|is_image[avatar]|max_size[avatar,4096]',
            ];
            $errorsMsg = [
                'name'    => [
                    'required'    => '真实姓名不能为空',
                    'regex_match' => '真实姓名为 2 至 10 个字符',
                ],
                'website' => [
                    'valid_url_strict' => '请输入有效的 URL'
                ],
                'avatar'  => [
                    'is_image' => '请上传头像图片',
                    'max_size' => '文件不能超过 4M',
                ],
            ];

            if (!$this->validate($rules, $errorsMsg)) {
                $errors = $this->validator->getErrors();

                throw new Exception(array_shift($errors));
            }

            $post   = $this->validator->getValidated();
            $avatar = $this->request->getFile('avatar');

            if ($avatar instanceof UploadedFile) {
                $user->avatar = CommonUtil::getUploadFilePath($avatar, 'avatar');
            }

            $data = ['name' => $post['name'], 'website' => $post['website'], 'avatar' => $user->avatar];
            db_connect()->table("user")->where("id", $user->id)->update($data);
        } catch (Exception $e) {
            return $this->responseMsg($e->getMessage());
        }

        return $this->responseMsg();
    }

    public function unzip(): \CodeIgniter\HTTP\ResponseInterface
    {
        helper('filesystem');

        try {
            $user = $this->getUser();

            $zipFile = $this->request->getFile('zip');

            if ($zipFile instanceof UploadedFile) {
                $name     = $zipFile->getRandomName();
                $zipPath  = WRITEPATH . "uploads/" . $zipFile->store("zip", $name);
                $unzipDir = WRITEPATH . "zip/{$user->username}";

                CommonUtil::deleteDir($unzipDir);

                $zip = new ZipArchive();
                if ($zip->open($zipPath) === TRUE) {
                    $zip->extractTo($unzipDir);
                    $zip->close();
                }
            }
        } catch (Exception $e) {
            return $this->responseMsg($e->getMessage());
        }

        return $this->responseMsg();
    }
}
